﻿using Face8280WebSocketServer.DB.Device;
using Face8280WebSocketServer.Interface;
using Face8280WebSocketServer.Model;
using Face8280WebSocketServer.Utility;
using Face8280WebSocketServer.Controllers.DeviceAPI;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using System.Linq;
using Face8280WebSocketServer.DB.Access.APIResult;

namespace Face8280WebSocketServer.Controllers
{
    [Route("[controller]")]
    [ApiController]
    //[ServiceFilter(typeof(FaceAPILogResourceFilter))]
    public class FaceAPIController : ControllerBase
    {

        private readonly ILogger<FaceAPIController> _logger;

        private IRecordService _RecordDB;
        private IFaceDriveService _DriveDB;
        private ITimeGroupService _TimeGroupDB;
        private IDeviceRemoteService _RemoteDB;
        private ICacheService _Cache;
        private IDeviceAccessService _AccessDB;

        public FaceAPIController(ILogger<FaceAPIController> logger, IMyMemoryCache mycache,
            IFaceDriveService faceDrive,
            IRecordService record, ITimeGroupService timegroupdb,
            IDeviceRemoteService remoteDB, ICacheService cache,
            IDeviceAccessService access)
        {
            _logger = logger;
            _RecordDB = record;
            _DriveDB = faceDrive;
            _TimeGroupDB = timegroupdb;
            _RemoteDB = remoteDB;
            _Cache = cache;
            _AccessDB = access;
        }

        #region 打卡记录
        /// <summary>
        /// 设备主动往云端实时上传打卡记录
        /// </summary>
        /// <param name="record"></param>
        /// <returns></returns>
        [Route("note/insertNoteFace")]
        [Route("/note/insertNoteFace")]
        [HttpPost]
        public async Task<JsonResult> UploadRecord([FromForm] string recordJson, [FromForm] IFormCollection files)
        {
            DriveRecord record = JsonConvert.DeserializeObject<DriveRecord>(recordJson);

            //_logger.LogInformation($"设备上传记录 note/insertNoteFace {record.DeviceID} {record.NoteTime} \r\n {recordJson}");
            if (record.Pic_Len > 0 && files.Files.Count == 1)
            {

                string sPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "RecordImage", record.DeviceID);
                if (!Directory.Exists(sPath))
                {
                    Directory.CreateDirectory(sPath);
                }
                string sFileName = $"{record.NoteTime.ToString("yyyy-MM-dd_HH_mm_ss")}_{Guid.NewGuid().ToString("N")}.jpg";
                string sFile = Path.Combine(sPath, sFileName);
                var uploadFile = files.Files[0];
                if (uploadFile.Length > 0)
                {
                    record.Pic_Len = (int)uploadFile.Length;

                    using (var stream = new FileStream(sFile, FileMode.Create))
                    {
                        await uploadFile.CopyToAsync(stream);
                    }
                    record.ImgURL = $"/RecordImage/{record.DeviceID}/{sFileName}";
                }
            }
            else
            {
                record.Pic_Len = 0;
                record.ImgURL = string.Empty;
            }
            _RecordDB.AddRecord(record);

            return new JsonResult(new FaceAPIResult());
        }
        #endregion


        #region 保活包
        /// <summary>
        /// 心跳保活包
        /// </summary>
        [Route("device/updateStateDevice")]
        [Route("/device/updateStateDevice")]
        [HttpPost]
        public IActionResult DeviceKeepalive([FromBody] DeviceKeepaliveRequest par)
        {
            var result = new DeviceKeepaliveResult();

            //_logger.LogInformation($" 设备心跳包 device/updateStateDevice SN:{par.DeviceID}");

            if (string.IsNullOrWhiteSpace(par.DeviceID))
            {
                result.SyncParameter = 1;
            }
            else
            {
                if (par.DeviceID.Length < 16 || par.DeviceID == "0000000000000000")
                {
                    result.SyncParameter = 1;
                }
                else
                {

                    #region 检查参数是否需要同步
                    FaceDeviceInfo oDevice = null;
                    //  oDevice = _Cache.GetDevice(par.DeviceID);
                    #endregion

                    if (oDevice != null)
                    {
                        #region 检查权限是否需要同步
                        int iAccessTotal;
                        int iEmptyPeople;
                        (result.AddPeople, result.DeletePeople, iAccessTotal, result.Remote, iEmptyPeople) = _Cache.GetTaskDetail(par.DeviceID);
                        if (result.DeletePeople == 0 && iEmptyPeople != 0)
                        {
                            result.DeletePeople = 1;
                        }

                        #endregion

                        //oDevice = _DriveDB.Find<FaceDeviceDetail>(oDevice.ID);
                        //oDevice.LastKeepaliveTime = DateTime.Now;
                        //oDevice.OnlineTime = DateTime.Now;
                        //oDevice.AlarmStatus = par.Alarm;
                        //oDevice.DoorStatus = par.Door;
                        //if (oDevice.UploadStatus == 0)
                        //{
                        //    result.SyncParameter = 1;
                        //}
                        _Cache.UpdateDeviceCache(oDevice, (x, y) =>
                        {
                            //x.Add("LastKeepaliveTime", y.LastKeepaliveTime.ToDateTimeStr());
                            //x.Add("OnlineTime", y.OnlineTime.ToDateTimeStr());
                            //x.Add("AlarmStatus", y.AlarmStatus.ToString());
                            //x.Add("DoorStatus", y.DoorStatus.ToString());
                        });
                    }
                }


            }

            return new JsonResult(result);
        }


        #endregion

        /// <summary>
        /// 检查设备是否已注册
        /// </summary>
        /// <param name="SN"></param>
        /// <param name="oDevice"></param>
        /// <returns></returns>
        private JsonResult CheckDeviceReg(string SN, out FaceDeviceInfo oDevice)
        {
            FaceAPIResult rst = new();
            oDevice = null;
            if (string.IsNullOrWhiteSpace(SN))
            {
                rst.success = 1;
                rst.msg = "设备未注册！";
                return new JsonResult(rst);
            }

            // oDevice = _Cache.GetDevice(SN);
            if (oDevice == null)
            {
                rst.success = 1;
                rst.msg = "设备未注册！";
                return new JsonResult(rst);
            }
            //更新连接时间
            //  oDevice.OnlineTime = DateTime.Now;
            _Cache.UpdateDeviceCache(oDevice, (x, y) =>
            {
                //     x.Add("OnlineTime", y.OnlineTime.ToDateTimeStr());
            });
            return null;
        }

        #region 人员操作
        /// <summary>
        ///  添加人员 设备主动触发云端导入雇员授权信息
        /// </summary>
        [Route("devicePass/selectPassInfo")]
        [Route("/devicePass/selectPassInfo")]
        [HttpPost]
        public IActionResult ReadPeople(ReadPeopleRequestRequest par)
        {
            _logger.LogInformation($" 设备拉取人事信息 ReadPeople SN:{par.DeviceID}");

            ReadPeopleResult rst = new();
            FaceDeviceInfo oDevice = null;
            var chkRet = CheckDeviceReg(par.DeviceID, out oDevice);
            if (chkRet != null) return chkRet;

            if (par.Limit == 0) par.Limit = 50;
            if (par.Limit > 100) par.Limit = 100;
            //检查有没有需要添加的人员
            var TotalDetail = _Cache.GetNewPeopleTotal(par.DeviceID);

            if (TotalDetail == 0)
            {
                //没有需要上传的人员
                rst.success = 2;
                rst.msg = "没有需要同步的人员!";
                return new JsonResult(rst);
            }
            //从数据库中获取需要导入的人员
            string sHost = this.HttpContext.Request.Host.Value;
            //if (this.HttpContext.Request.IsHttps)
            //{
            //    sHost = "Https://" + sHost;
            //}
            //else
            //{
            //    sHost = "Http://" + sHost;
            //}
            rst.PassInfo = _AccessDB.GetSyncAccessbyDoorID(par.DeviceID, oDevice.Id, par.Limit);
            //foreach (var item in rst.PassInfo)
            //{
            //    if (item.EmployeePhotoWay == "path")
            //    {
            //        if (!item.EmployeePhoto.ToLower().StartsWith("http"))
            //        {
            //            if (item.EmployeePhoto.StartsWith("/"))

            //                item.EmployeePhoto = sHost + item.EmployeePhoto;
            //            else
            //                item.EmployeePhoto = sHost + "/" + item.EmployeePhoto;
            //        }
            //    }
            //}

            _Cache.SaveDeviceReadPeopleCodeList(par.DeviceID, rst.PassInfo.Select(x => x.EmployeeID));

            return new JsonResult(rst);
        }

        /// <summary>
        /// 添加人员反馈  拉取人员导入人脸机后的结果反馈
        /// </summary>
        [Route("devicePass/setPassResult")]
        [Route("/devicePass/setPassResult")]
        [HttpPost]
        public IActionResult ReadPeopleResult([FromBody] DeviceReadPeopleResultRequest par)
        {
            _logger.LogInformation($" 设备推送人事保存结果 ReadPeopleResult SN:{par.DeviceID}");
            FaceDeviceInfo oDevice = null;
            var chkRet = CheckDeviceReg(par.DeviceID, out oDevice);
            if (chkRet != null) return chkRet;


            List<APIRequest_PeopleInfo> peopleInfos = null;
            if (par.FailNumber > 0)
            {
                peopleInfos = par.FailEmployeeId.Select(x => new APIRequest_PeopleInfo()
                {
                    EmployeeID = x.EmployeeID,
                    ErrCode = x.ErrorCode,
                    RepeatID = x.RepeatID

                }).ToList();
            }

            _AccessDB.SavePeopleAccessUploadResult(par.DeviceID, par.FailNumber, peopleInfos);


            return new JsonResult(new FaceAPIResult());
        }



        /// <summary>
        /// 删除人员   拉取待删除的人员
        /// </summary>
        [Route("devicePass/selectDeleteInfo")]
        [Route("/devicePass/selectDeleteInfo")]
        [HttpPost]
        public IActionResult DeletePeople([FromBody] ReadPeopleRequestRequest par)
        {
            _logger.LogInformation($" 设备拉取待删除人员 DeletePeople SN:{par.DeviceID}");

            DeletePeopleResult rst = new();
            FaceDeviceInfo oDevice = null;
            var chkRet = CheckDeviceReg(par.DeviceID, out oDevice);
            if (chkRet != null) return chkRet;




            //检查有没有需要删除的人员
            var TaskDetail = _Cache.GetTaskDetail(par.DeviceID);

            if (TaskDetail.DelPeople == 0 && TaskDetail.EmptyPeople == 0)
            {
                //没有需要上传的人员
                rst.success = 2;
                rst.msg = "没有需要删除的人员!";
                return new JsonResult(rst);
            }

            if (TaskDetail.AccessTotal == 0 || TaskDetail.EmptyPeople > 0)
            {
                //需要删除所有人员
                rst.Empty = 1;
                rst.success = 0;
                rst.msg = "删除所有人员";
                _AccessDB.AddUserLog("权限管理", $"设备SN:{par.DeviceID} ，请求清空人员命令");
                return new JsonResult(rst);
            }

            if (par.Limit == 0) par.Limit = 50;
            if (par.Limit > 100) par.Limit = 100;

            //从数据库中获取需要删除的人员
            rst.DeleteInfo = _AccessDB.GetDeleteAccessbyDoorID(par.DeviceID, oDevice.Id, par.Limit);

            _Cache.SaveDeviceDeletePeopleCodeList(par.DeviceID, rst.DeleteInfo.Select(x => x.EmployeeID));


            return new JsonResult(rst);
        }

        /// <summary>
        /// 删除人员反馈   设备从服务器拉取的待删除的人员操作后的结果反馈
        /// </summary>
        [Route("devicePass/setDeleteResult")]
        [Route("/devicePass/setDeleteResult")]
        [HttpPost]
        public async Task<IActionResult> ReadDeletePeople([FromBody] DeviceDeletePeopleResultRequest par)
        {
            _logger.LogInformation($" 设备推送删除人员操作结果 ReadDeletePeople SN:{par.DeviceID}");

            var chkRet = CheckDeviceReg(par.DeviceID, out FaceDeviceInfo oDevice);
            if (chkRet != null) return chkRet;

            await _AccessDB.SaveDeleteAccessUploadResult(par.DeviceID, par.DeleteAll);

            return new JsonResult(new FaceAPIResult());
        }
        #endregion

        #region 远程操作指令
        /// <summary>
        /// 远程操作 设备请求远程操作任务
        /// </summary>
        /// <param name="par"></param>
        /// <returns></returns>
        [Route("device/selectRestart")]
        [Route("/device/selectRestart")]
        [HttpPost]
        public IActionResult DeviceRemote([FromBody] DeviceRemoteRequest par)
        {
            var chkRet = CheckDeviceReg(par.DeviceID, out FaceDeviceInfo oDevice);
            if (chkRet != null) return chkRet;

            var Remotes = _RemoteDB.GetRemoteTaskByDeviceID(oDevice.Id);

            var result = new DeviceRemoteResult();

            foreach (var item in Remotes)
            {
                switch (item.TaskType)
                {
                    case 1://1，远程开门
                        result.Opendoor = 1;
                        break;
                    case 2://2、远程重启
                        result.Restart = 1;
                        break;
                    case 3://3、恢复出厂设置
                        result.Recover = 1;
                        break;
                    case 4://4、关闭报警
                        result.Closealarm = 1;
                        break;
                    case 5://5、清空所有人员
                        return new JsonResult(result);
                    default:
                        break;
                }
                _RemoteDB.UpdateTaskRunStatusComplete(oDevice.Id, item.TaskType);
            }

            return new JsonResult(result);
        }
        #endregion


        #region 属性配置
        /// <summary>
        ///  上传参数 设备将机器现有配置上传服务器
        /// </summary>
        /// <param name="par"></param>
        /// <returns></returns>
        [Route("parameter/inertParameter")]
        [Route("/parameter/inertParameter")]
        [HttpPost]
        public IActionResult UploadWorkParameter([FromBody] FaceDeviceInfo par)
        {
            _logger.LogInformation($" 设备上传参数 parameter/inertParameter SN:{par.DeviceSn}");

            if (string.IsNullOrWhiteSpace(par.DeviceSn))
            {
                return new JsonResult(new FaceAPIResult());//没有SN不处理
            }

            if (par.DeviceSn.Length < 15 || par.DeviceSn == "0000000000000000")
            {
                return new JsonResult(new FaceAPIResult());//没有SN不处理
            }

            par.DeviceName = par.DeviceSn;

            // _DriveDB.Add(par);
            _Cache.UpdateDeviceCache(par, (x, y) =>
            {
                //  x.Add("OnlineTime", y.OnlineTime.ToDateTimeStr());
            });
            return new JsonResult(new FaceAPIResult());
        }

        /// <summary>
        ///  拉取参数 设备请求同步参数，将服务器存储内容发送到设备
        /// </summary>
        /// <param name="par"></param>
        /// <returns></returns>
        [Route("parameter/selectParameterInfo")]
        [Route("/parameter/selectParameterInfo")]
        [HttpPost]
        public IActionResult GetWorkParameter([FromBody] BaseDeviceRequest par)
        {
            _logger.LogInformation($" 设备拉取参数 parameter/selectParameterInfo SN:{par.DeviceID}");

            GetWorkParameterResult detail = new GetWorkParameterResult();

            void setDef()
            {
                var defValue = _DriveDB.GetDefaultValue();

                //从数据库拉取默认值发过去
                defValue.ParameterProductionDate = DateTime.Now.ToDateTimeStr();

                defValue.DeviceName = "-";
                defValue.ParameterSerialNum = defValue.DeviceID;
                detail.SetFaceDeviceDetail(defValue);

                FaceDeviceInfo newDevice = new();
                //defValue.CopyTo(newDevice);

                ////将设备加入到列表中
                //_DriveDB.Add(newDevice);
                _Cache.UpdateDeviceCache(newDevice, (x, y) =>
                {
                    // x.Add("OnlineTime", y.OnlineTime.ToDateTimeStr());

                });

                defValue.ID = 0;
                string sSNNum = defValue.DeviceID.Substring(10, 6);
                sSNNum = (sSNNum.ToInt32() + 1).ToString("000000");

                defValue.DeviceID = defValue.DeviceID.Substring(0, 10) + sSNNum;

                _DriveDB.SaveDefaultValue(defValue);




            }

            if (string.IsNullOrWhiteSpace(par.DeviceID))
            {
                setDef();

            }
            else
            {
                if (par.DeviceID.Length < 15 || par.DeviceID == "0000000000000000")
                {
                    setDef();
                }
                else
                {
                    var chkRet = CheckDeviceReg(par.DeviceID, out FaceDeviceInfo oDevice);
                    if (chkRet != null) return chkRet;
                    oDevice = _DriveDB.Find<FaceDeviceInfo>(oDevice.Id);
                    //detail = oDevice.ToJSON().FromJson<GetWorkParameterResult>();

                    var softCache = new Dictionary<string, string>();
                    _Cache.GetDeviceCacheHashValue(oDevice.DeviceSn, new HashSet<string>(new string[] {
                    "UpdateSoftURL","UpdateSoftVer","UpdateSoftMD5" }), softCache);

                    if (!string.IsNullOrEmpty(softCache["UpdateSoftURL"]) && !string.IsNullOrEmpty(softCache["UpdateSoftMD5"]))
                    {
                        detail.parameterFirmwareMd5 = softCache["UpdateSoftMD5"];
                        detail.parameterFirmwarePath = softCache["UpdateSoftURL"];
                        detail.ParameterFirmwareMsg = softCache["UpdateSoftVer"];
                    }
                    //oDevice.UploadStatus = 1;
                    //oDevice.UploadStatusTime = DateTime.Now;
                    _Cache.UpdateDeviceCache(oDevice, (x, y) =>
                    {
                        //x.Add("UploadStatus", y.UploadStatus.ToString());
                        //x.Add("UploadStatusTime", y.UploadStatusTime.ToDateTimeStr());
                        x.Add("UpdateSoftMD5", null);
                        x.Add("UpdateSoftURL", null);
                        x.Add("UpdateSoftVer", null);
                    });
                    // detail.SetFaceDeviceDetail(oDevice);

                    //if (oDevice.ParameterSerialNum != oDevice.DeviceID)
                    //{
                    //    if (oDevice.ParameterSerialNum == "0000000000000000")
                    //    {
                    //        //删除
                    //        _DriveDB.Delete(oDevice);

                    //    }
                    //    else
                    //    {
                    //        //更新SN
                    //        _Cache.ReplaceDeviceSN(oDevice.DeviceID, oDevice.ParameterSerialNum);


                    //    }
                    //    oDevice.DeviceID = oDevice.ParameterSerialNum;

                    //}

                    _DriveDB.Commit();
                }



            }


            detail.ParameterSystemTime = TimestampUtility.ToUnixTimestampBySeconds(DateTime.Now);
            detail.Timegroups = _TimeGroupDB.GetAll();


            return new JsonResult(detail);
        }


    }
    #endregion


}
